#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "MDL/MDL_Uart/MDL_Uart_Ringbuffer.h"

// Helper function to print buffer status
void print_buffer_status(uart_ringbuffer_t *rb) {
    printf("  Buffer status - Head: %d, Tail: %d, Count: %d, Size: %d\n", 
           rb->head, rb->tail, rb->count, rb->size);
    printf("  Is empty: %s, Is full: %s\n", 
           uart_ringbuffer_is_empty(rb) ? "Yes" : "No",
           uart_ringbuffer_is_full(rb) ? "Yes" : "No");
}

// Helper function to print all values in the ring buffer
void print_buffer_contents(uart_ringbuffer_t *rb) {
    printf("  Buffer contents: ");
    if (rb->count == 0) {
        printf("(empty)\n");
        return;
    }
    
    // Print all data in the buffer in order
    uint16_t index = rb->tail;
    for (uint16_t i = 0; i < rb->count; i++) {
        printf("%d ", rb->buffer[index]);
        index = (index + 1) & (rb->size - 1);
    }
    printf("\n");
}

int main() {
    // Create a buffer for testing
    uint8_t buffer[16];
    uart_ringbuffer_t rb;
    
    // Initialize ring buffer
    uart_ringbuffer_init(&rb, buffer, sizeof(buffer));
    
    printf("Ring Buffer Test Started\n");
    printf("Buffer Size: %d\n", rb.size);
    print_buffer_status(&rb);
    print_buffer_contents(&rb);
    
    // Test writing data
    uint8_t test_data1[] = {1, 2, 3, 4, 5};
    uint16_t written = uart_ringbuffer_write(&rb, test_data1, sizeof(test_data1));
    printf("Wrote %d bytes of data: ", written);
    for (int i = 0; i < written; i++) {
        printf("%d ", test_data1[i]);
    }
    printf("\n");
    print_buffer_status(&rb);
    print_buffer_contents(&rb);
    
    // Test reading data
    uint8_t read_data[10];
    uint16_t read_count = uart_ringbuffer_read(&rb, read_data, 3);
    printf("Read %d bytes of data: ", read_count);
    for (int i = 0; i < read_count; i++) {
        printf("%d ", read_data[i]);  // 显示从缓冲区读取的实际数据
    }
    printf("\n");
    print_buffer_status(&rb);
    print_buffer_contents(&rb);
    
    // Write some more data
    uint8_t test_data2[] = {6, 7, 8, 9, 10, 11, 12};
    written = uart_ringbuffer_write(&rb, test_data2, sizeof(test_data2));
    printf("Wrote another %d bytes of data: ", written);
    for (int i = 0; i < written; i++) {
        printf("%d ", test_data2[i]);
    }
    printf("\n");
    print_buffer_status(&rb);
    print_buffer_contents(&rb);
    
    // Read all remaining data
    read_count = uart_ringbuffer_read(&rb, read_data, sizeof(read_data));
    printf("Read remaining %d bytes of data: ", read_count);
    for (int i = 0; i < read_count; i++) {
        printf("%d ", read_data[i]);  // 显示从缓冲区读取的实际数据
    }
    printf("\n");
    print_buffer_status(&rb);
    print_buffer_contents(&rb);
    
    // Test buffer full condition
    printf("\nTesting buffer full condition:\n");
    uint8_t large_data[20];
    for (int i = 0; i < 20; i++) {
        large_data[i] = i + 1;
    }
    
    written = uart_ringbuffer_write(&rb, large_data, sizeof(large_data));
    printf("Tried to write 20 bytes, actually wrote %d bytes\n", written);
    printf("Overflow count: %d\n", uart_ringbuffer_get_overflow_count(&rb));
    print_buffer_status(&rb);
    print_buffer_contents(&rb);
    
    // Read all data
    read_count = uart_ringbuffer_read(&rb, read_data, sizeof(read_data));
    printf("Read %d bytes of data: ", read_count);
    for (int i = 0; i < read_count; i++) {
        printf("%d ", read_data[i]);  // 显示从缓冲区读取的实际数据
    }
    printf("\n");
    print_buffer_status(&rb);
    print_buffer_contents(&rb);
    
    // Test reading from empty buffer
    printf("\nTesting read from empty buffer:\n");
    read_count = uart_ringbuffer_read(&rb, read_data, sizeof(read_data));
    printf("Read %d bytes from empty buffer: ", read_count);
    for (int i = 0; i < read_count; i++) {
        printf("%d ", read_data[i]);  // 显示从缓冲区读取的实际数据
    }
    printf("\n");
    printf("Is buffer empty: %s\n", uart_ringbuffer_is_empty(&rb) ? "Yes" : "No");
    print_buffer_status(&rb);
    print_buffer_contents(&rb);
    
    printf("\nTest completed\n");
    return 0;
}